//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop   //缓存头文件预处理内容
#include <string>
#include <process.h>
#include <shlwapi.h>
#include "unitListView.h"
#include "Unit1.h"
#include <iostream>
#include <fstream>
#pragma comment(lib, "shlwapi.lib")
TStringList *list;
HANDLE hEvent;
int cnt;
int g=0;
int g5= 0;
ofstream infile;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	list = new TStringList;
	SetColumnProperty(ListView1, 1, "序号", 60, true);
	SetColumnProperty(ListView1, 2, "动作", 100, true);
	SetColumnProperty(ListView1, 3, "路径", 400, true);

	DWORD dwLen = GetLogicalDriveStrings(0, NULL);	//获取系统字符串长度.
	char * pszDriver = new char[dwLen];				//构建一个相应长度的数组.
	GetLogicalDriveStringsA(dwLen, pszDriver);		//获取盘符字符串.

	infile.open("C:\\log\\watcher_log.txt");

	while(*pszDriver != '\0'){
		int a = strlen(pszDriver);
		UINT uDriveType = GetDriveTypeA(pszDriver);
		if(uDriveType != DRIVE_CDROM){
			ComboBox1->Items->Add(pszDriver);
        }
		pszDriver += strlen(pszDriver) + 1;			//定位到下一个字符串.加一是为了跳过'\0'字符串.
	}
	ComboBox1->ItemIndex = 0;

	hEvent = CreateEvent(NULL, true, FALSE, NULL);
	cnt = 0;
}
//---------------------------------------------------------------------------
void fileWatcher(void *arg)
{
	TForm1 *frm = (TForm1 *)arg;
	DWORD cbBytes;
	char file_name[MAX_PATH] = {0}; //设置文件名;
	char file_rename[MAX_PATH] = {0}; //设置文件重命名后的名字;
	char notify[1024] = {0};
	int count = 0; //文件数量。可能同时拷贝、删除多个文件，可以进行更友好的提示;
    AnsiString dir = frm->ComboBox1->Text;
	HANDLE dirHandle = CreateFileA(dir.c_str(), // 句柄 获取目标目录
        GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY,
		FILE_SHARE_READ | FILE_SHARE_WRITE  | FILE_SHARE_DELETE,
        NULL,
		OPEN_EXISTING,
		FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,  //管理员运行
        NULL);

    if (dirHandle == INVALID_HANDLE_VALUE) //若网络重定向或目标文件系统不支持该操作，函数失败，同时调用GetLastError()返回ERROR_INVALID_FUNCTION
	{
		frm->Memo1->Lines->Add("error");
	}

	memset(notify, 0, strlen(notify));
	FILE_NOTIFY_INFORMATION *pnotify = (FILE_NOTIFY_INFORMATION*)notify;  // 对pNotify对象进行了填充


    while (true)
	{
		DWORD dwReturn = WaitForSingleObject(hEvent, INFINITE);
		if(dwReturn == WAIT_OBJECT_0)
		{
			if (ReadDirectoryChangesW(dirHandle, &notify, 1024, true,
				FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE,
				&cbBytes, NULL, NULL))
			{
				//转换文件名为多字节字符串;
				if (pnotify->FileName)
				{
					memset(file_name, 0, strlen(file_name));
					WideCharToMultiByte(CP_ACP, 0, pnotify->FileName, pnotify->FileNameLength / 2, file_name, 99, NULL, NULL);
				}

				//获取重命名的文件名;
				if (pnotify->NextEntryOffset != 0 && (pnotify->FileNameLength > 0 && pnotify->FileNameLength < MAX_PATH))
				{
					PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pnotify + pnotify->NextEntryOffset);
					memset(file_rename, 0, sizeof(file_rename));
					WideCharToMultiByte(CP_ACP, 0, p->FileName, p->FileNameLength / 2, file_rename, 99, NULL, NULL);
				}

				std::string fn = std::string(file_name);
				std::string dir_name = std::string(dir.c_str());
				std::string wn("watcher_log");
				int pos = fn.find(wn);
				if(pos < 0){
				++cnt;
				list->Clear();
				list->Add("");
				list->Add(AnsiString(cnt));
				//设置类型过滤器,监听文件创建、更改、删除、重命名等;
				switch (pnotify->Action)
				{
					case FILE_ACTION_ADDED:
						{
							count++;
							LPCSTR name;
							LPCSTR ext;
							name = PathFindFileNameA(file_name);
							ext= PathFindExtensionA(file_name);
							AnsiString str_ext = AnsiString(ext);
							list->Add("新增");
							list->Add(AnsiString(dir) + "\\"+AnsiString(file_name));
							infile << cnt << "	"  << "新增" << "	" <<  dir_name <<  "\\" <<  fn   <<  std::endl;
						}

						break;

					case FILE_ACTION_MODIFIED:
						{
							LPCSTR name;
							LPCSTR ext;
							name = PathFindFileNameA(file_name);
							ext= PathFindExtensionA(file_name);
							AnsiString str_ext = AnsiString(ext);
							list->Add("修改");
							list->Add(AnsiString(dir) + "\\"+AnsiString(file_name));
							infile << cnt << "	"  <<  "修改" << "	" << dir_name << "\\" <<  fn   << std::endl;

						}
						break;

					case FILE_ACTION_REMOVED:
					{
						count--;
						LPCSTR name;
						LPCSTR ext;
						name = PathFindFileNameA(file_name);
						ext= PathFindExtensionA(file_name);
						AnsiString str_ext = AnsiString(ext);
						list->Add("删除");
						list->Add(AnsiString(dir) + "\\"+AnsiString(file_name));
						infile << cnt << "	"  <<  "删除" << "	" << dir_name << "\\" <<  fn   << std::endl;

						break;
					}
					case FILE_ACTION_RENAMED_OLD_NAME:
					{
						LPCSTR name;
						LPCSTR ext;
						name = PathFindFileNameA(file_name);
						ext= PathFindExtensionA(file_name);
						AnsiString str_ext = AnsiString(ext);
						list->Add("重命名");
						list->Add(AnsiString(dir) + "\\"+AnsiString(file_rename));
						infile << cnt << "	"  <<  "重命名" << "	" << dir_name << "\\" << fn   << std::endl;
						break;
					}


					default:
						frm->Memo1->Lines->Add("UNknow command!" + AnsiString(file_name));
						infile << "UNknow command!" << "	" << fn   << std::endl;
				}
				}
				InsertDataToList(frm->ListView1, list, 0);
			}
		}
		if(g5==5) {
			return ;
        }
	}

	CloseHandle(dirHandle);
	infile.close();
}
void __fastcall TForm1::Button3Click(TObject *Sender)
{
	Memo1->Lines->Add("开始监控" + ComboBox1->Text + "盘");
	if(g==0){
		_beginthread(fileWatcher, 0, this);
		g=5;
		g5=6;
	}
	SetEvent(hEvent);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
	Memo1->Lines->Add("暂停监控" + ComboBox1->Text + "盘");
	Memo1->Lines->Add("监控记录已存放于watcher_log.txt");
	ResetEvent(hEvent);
	 g5=5;
	 g= 0 ;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	ListView1->Items->Clear();
	cnt = 0;
}
//---------------------------------------------------------------------------


